import {
  PerspectiveCamera,
  OrthographicCamera,
  WebGLRenderer,
  Scene,
  Color,
  DirectionalLight,
  Box3,
  Vector3,
  Box3Helper,
  HemisphereLight,
  LightProbe,
  Group,
  Raycaster,
  Vector2
} from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"

export function createBasicFramework(config, currentDomRef) {
  //初始化场景、相机、渲染器
  config.framework = {

  }
  /**
   * 获取窗口大小
   * @returns 
   */
  function getDomSize() {
    return {
      width: currentDomRef.value.clientWidth,
      height: currentDomRef.value.clientHeight
    }
  }
  /**
   * 初始化场景
   */
  function initScene() {
    config.framework.scene = new Scene()
    config.framework.scene.background = new Color(0xFFFFFF)
  }

  /**
   * 初始化模型容器
   */
  function initModels() {
    config.framework.models = new Group()
    config.framework.scene.add(config.framework.models)
  }

  /**
   * 初始化相机
   */
  function initCamera() {
    // 创建两种相机
    if (config.cameraType === 'Orthographic') {
      config.framework.camera = createOrthographicCamera()
    } else {
      config.framework.camera = createPerspectiveCamera()
    }
    config.framework.camera.position.set(0, 0, 5000);
    config.framework.camera.lookAt(0, 0, 0);
  }

  /**
   * 创建透视相机
   * @returns 
   */
  function createPerspectiveCamera() {
    let { width, height } = getDomSize()
    return new PerspectiveCamera(
      35, width / height, 0.1, 10000
    );
  }

  /**
   * 创建正交相机
   * @returns 
   */
  function createOrthographicCamera() {
    let { width, height } = getDomSize()
    const aspect = width / height;
    const bbox = new Box3().setFromObject(config.framework.models);
    const size = bbox.getSize(new Vector3());
    const maxDim = Math.max(size.x, size.y, size.z);

    return new OrthographicCamera(
      -maxDim * aspect / 2, // left
      maxDim * aspect / 2,  // right
      maxDim / 2,           // top
      -maxDim / 2,          // bottom
      0.1,                  // near
      maxDim * 10           // far
    );
  }

  //初始化渲染器
  function initRender() {
    let { width, height } = getDomSize()
    config.framework.renderer = new WebGLRenderer({
      antialias: true
    })
    config.framework.renderer.setSize(width, height)
    //支持阴影
    config.framework.renderer.shadowMap.enabled = true

    currentDomRef.value.append(config.framework.renderer.domElement)
  }

  //初始化轨道控制器
  function initControls() {

    config.framework.controls = new OrbitControls(config.framework.camera, config.framework.renderer.domElement);
    //声明有惯性
    config.framework.controls.enableDamping = true;
    config.framework.controls.dampingFactor = 0.05;

    // 根据相机类型设置不同参数
    if (config.cameraType === 'Orthographic') {
      config.framework.controls.zoomSpeed = 2.0;
      config.framework.controls.minZoom = 0.1;
      config.framework.controls.maxZoom = 5;
    } else {
      // controls.minDistance = 1;
      // controls.maxDistance = 100;
    }
    config.framework.controls.enableDamping = true; // 启用阻尼效果
    config.framework.controls.dampingFactor = 0.05; // 默认0.25，减小这个值使运动更灵敏
    
    // 解决 OrbitControls 与 quaternion.multiplyQuaternions 冲突问题
    config.framework.controls.enableRotate = false; // 完全禁用旋转

    // controls.maxDistance = 15000
    // controls.minDistance = 1
  }

  // 添加光源
  function initLights() {
    // 主定向光增强
    const mainLight = new DirectionalLight(0xffffff, 2.0); // 强度提高到2
    mainLight.position.set(5, 10, 7);
    mainLight.castShadow = true;
    config.framework.scene.add(mainLight);

    // 补充辅助光
    const fillLight1 = new DirectionalLight(0xffffff, 0.8);
    fillLight1.position.set(-5, 5, 5);
    config.framework.scene.add(fillLight1);

    const fillLight2 = new HemisphereLight(0xffffff, 0x444444, 1.5);
    config.framework.scene.add(fillLight2);
    const lightProbe = new LightProbe();
    lightProbe.intensity = 2.0; // 提高光探针强度
    config.framework.scene.add(lightProbe);


    // const ambientLight = new AmbientLight(0xffffff, 1);
    // scene.add(ambientLight);

    // const directionalLight = new DirectionalLight(0xffffff, 1.5);
    // directionalLight.position.set(1, 1, 1);
    // scene.add(directionalLight);
  }
  //动画
  function render() {
    config.framework.renderer.render(config.framework.scene, config.framework.camera)
    requestAnimationFrame(render)
    config.framework.controls.update()
  }

  function listenerResize() {
    // 监听视口的改变
    window.addEventListener("resize", () => {
      let { width, height } = getDomSize()

      const aspect = width / height;
      config.framework.camera.aspect = aspect;

      if (config.framework.camera.isOrthographicCamera) {
        const bbox = new Box3().setFromObject(config.framework.models);
        const size = bbox.getSize(new Vector3());
        const maxDim = Math.max(size.x, size.y, size.z);
        const zoomFactor = maxDim * 1.5;

        config.framework.camera.left = -zoomFactor * aspect / 2;
        config.framework.camera.right = zoomFactor * aspect / 2;
        config.framework.camera.top = zoomFactor / 2;
        config.framework.camera.bottom = -zoomFactor / 2;
      }

      config.framework.camera.updateProjectionMatrix();
      config.framework.renderer.setSize(width, height)

      // 更新控制器
      config.framework.controls.update();
    })
  }

  initScene()
  initModels()
  initCamera()
  initRender()
  initControls()
  initLights()
  render()
  listenerResize()
  
  Object.assign(config.framework, {
    createPerspectiveCamera,
    createOrthographicCamera,
  })
}

/**
 * 设置场景背景色
 * @param {*} color 
 */
export function setSceneBackground(color) {
  this.framework.scene.background = new Color(color);
}

/**
 * 将2D屏幕坐标转换为3D世界坐标
 * @param {*} screenX 
 * @param {*} screenY 
 * @param {*} depth 
 * @returns 
 */
export function getScreenToWorld (screenX, screenY, depth = 0) {
  // 归一化设备坐标 (NDC)
  const x = (screenX / this.framework.renderer.domElement.clientWidth) * 2 - 1;
  const y = -(screenY / this.framework.renderer.domElement.clientHeight) * 2 + 1;

  // 创建射线
  const raycaster = new Raycaster();
  raycaster.setFromCamera(new Vector2(x, y), this.framework.camera);

  // 计算在指定深度的3D位置
  const position = new Vector3();
  position.copy(raycaster.ray.direction);
  position.multiplyScalar(depth);
  position.add(raycaster.ray.origin);

  return position;
};

/**
 * 相机切换函数
 * @param {*} type 
 */
export function setCamera(type) {
  let {createOrthographicCamera, createPerspectiveCamera} = this.framework
  const oldTarget = this.framework.controls.target.clone();
  type === 'Orthographic' && (this.framework.camera = createOrthographicCamera())
  type === 'Perspective' && (this.framework.camera = createPerspectiveCamera())
  // 保持原目标位置
  this.framework.controls.target.copy(oldTarget);
  this.framework.controls.object = this.framework.camera;
  this.framework.controls.update();
  // controls = config.framework.controls
  // camera = config.framework.camera;
  this.framework.fitModelToViewport();
}

/**
 * 让模型显示在可使区域内
 * @returns 
 */
export function fitModelToViewport() {
    let {scene, models,camera, renderer, controls} = this.framework
    // 1. 验证模型状态
    if (!models || !models.isObject3D) {
      console.error("提供的模型不是有效的Three.js对象");
      return;
    }

    // 2. 强制更新模型矩阵
    models.updateMatrixWorld(true);
    const bbox = new Box3().setFromObject(models);
    if (bbox.isEmpty()) {
      console.error("模型包围盒为空，请检查模型内容");
      return;
    }

    const size = bbox.getSize(new Vector3());
    const center = bbox.getCenter(new Vector3());
    const maxDim = Math.max(size.x, size.y, size.z);
    const aspect = renderer.domElement.width / renderer.domElement.height;


    // 透视相机逻辑
    if (camera.isPerspectiveCamera) {
      // 透视相机处理
      const fovRad = camera.fov * (Math.PI / 180);
      let distance = (maxDim / Math.tan(fovRad / 2)) * 1;

      camera.position.set(
        center.x,
        center.y,
        center.z + Math.max(distance, maxDim * 1.5)
      );

      camera.near = Math.max(distance, maxDim * 1.5) * 0.1; // 动态近平面
      camera.far = Math.max(distance, maxDim * 1.5) * 100;  // 动态远平面
    } else {
      // 正交相机逻辑
      const zoomFactor = maxDim * 1.5;
      camera.left = -zoomFactor * aspect / 2;
      camera.right = zoomFactor * aspect / 2;
      camera.top = zoomFactor / 2;
      camera.bottom = -zoomFactor / 2;
      camera.near = -maxDim * 10;
      camera.far = maxDim * 10;
      camera.zoom = 1;

      camera.position.set(
        center.x,
        center.y,
        center.z + maxDim * 2
      );
    }

    // 6. 调试可视化（可选）
    const helper = new Box3Helper(bbox, 0xffff00);
    scene.add(helper);
    setTimeout(() => scene.remove(helper), 1000);

    camera.lookAt(center);
    controls.target.copy(center);
    controls.update();
    camera.updateMatrixWorld(true); // 强制更新矩阵
    camera.updateProjectionMatrix();
  }